/////////  comment  //////////

#include <cstring>
#include <iostream>
#include <string>
#include <stdlib.h>
#include <vector>
#include "stringutil.h"

// Case conversions...
std::string lowerString( const std::string& src ) {
	std::string temp = src;
	std::string dest;
	for ( unsigned u=0; u < temp.length(); ++u )
		dest += LOWER( temp[u] );
	return dest;
}

std::string upperString( const std::string& src ) {
	std::string temp = src;
	std::string dest;
	for ( unsigned u=0; u < temp.length(); ++u )
		dest += UPPER( temp[u] );
	return dest;
}

// Whitespace removal functions (modeled after php's trim() family of functions)...
std::string trim( const std::string& src ) {
	std::string dest = src;
	dest = ltrim( dest );
	dest = rtrim( dest );
	return dest;
}

std::string ltrim( const std::string& src ) {
	std::string dest = src;
	while ( isspace( dest[dest.length()-1] ) )
		dest.erase( dest.length()-1, 1 );
	return dest;
}

std::string rtrim( const std::string& src ) {
	std::string dest = src;
	while ( isspace( dest[0] ) )
		dest.erase( 0, 1 );
	return dest;
}

std::string loginTrim( const std::string& src ) {
	std::string dest = src;
	while ( !isalpha( dest[dest.length()-1] ) )
		dest.erase( dest.length()-1, 1 );
	while ( !isalpha( dest[0] ) )
		dest.erase( 0, 1 );
	return dest;
}

char* cprint_private( char c ) {
	switch ( c ) {
		// colors
		case 'r': return "\033[40;31m"; break;		// dark red
		case 'R': return "\033[40;31;1m"; break;	// bright red
		case 'g': return "\033[40;32m"; break;		// dark green
		case 'G': return "\033[40;32;1m"; break;	// bright green
		case 'y': return "\033[40;33m"; break;		// dark yellow or brown
		case 'Y': return "\033[40;33;1m"; break;	// bright yellow
		case 'b': return "\033[40;34m"; break;		// dark blue
		case 'B': return "\033[40;34;1m"; break;	// bright blue
		case 'm': return "\033[40;35m"; break;		// dark magenta
		case 'M': return "\033[40;35;1m"; break;	// bright magenta
		case 'c': return "\033[40;36m"; break;		// dark cyan
		case 'C': return "\033[40;36;1m"; break;	// bright cyan
		case 'W': return "\033[40;37;1m"; break;	// pure white
		case 'w': return "\033[1;30m"; break;		// dark gray or black
		case '{': return "{"; break;				// a plain brace
		default: return "\033[0;0;0m"; break;		// default gray
	}
}

char* cprint_private( char c, char d ) {
	if ( c == '!' ) { // Underline
		switch ( d ) {
			case 'R': return "\033[31;4m\033[1m"; break;	// bright red
			case 'r': return "\033[31;4m"; break;			// dark red
			case 'G': return "\033[32;4m\033[1m"; break;	// bright green
			case 'g': return "\033[32;4m"; break;			// dark green
			case 'Y': return "\033[33;4m\033[1m"; break;	// bright yellow
			case 'y': return "\033[33;4m"; break;			// dark yellow
			case 'B': return "\033[34;4m\033[1m"; break;	// bright blue
			case 'b': return "\033[34;4m"; break;			// dark blue
			case 'M': return "\033[35;4m\033[1m"; break;	// bright magenta
			case 'm': return "\033[35;4m"; break;			// dark magenta
			case 'C': return "\033[36;4m\033[1m"; break;	// bright cyan
			case 'c': return "\033[36;4m"; break;			// dark cyan
			case 'W': return "\033[37;4m\033[1m"; break;	// bright white
			case 'w': return "\033[37;4m"; break;			// dark gray or black
			default: return "\033[0;0;0m"; break;			// default
		}
	}
	if ( c == '@' ) { // Highlight
		switch ( d ) {
			case 'R': case 'r': return "\033[40;31;7m"; break;	// red
			case 'G': case 'g': return "\033[40;32;7m"; break;	// green
			case 'Y': case 'y': return "\033[40;33;7m"; break;	// yellow
			case 'B': case 'b': return "\033[40;34;7m"; break;	// blue
			case 'M': case 'm': return "\033[40;35;7m"; break;	// magenta
			case 'C': case 'c': return "\033[40;36;7m"; break;	// cyan
			case 'W': case 'w': return "\033[40;37;7m"; break;	// gray
			default: return "\033[0;0;0m"; break;				// default
		}
	}

	return "\033[0;0m";
}

std::string spaces( const unsigned& space, const std::string& message ) {
	std::string temp;
	temp.assign( message.length() - space, ' ' );
	return temp;
}

std::string& spaces( const unsigned& space, const std::string& message, std::string& temp ) {
	temp.assign( message.length() - space, ' ' );
	return temp;
}

std::string format( const unsigned& length, const std::string& message, char color ) {
	std::string temp;
	temp << '{' << color << message;
	for ( unsigned u = message.length(); u < length; ++u )
		temp << ' ';
	temp << "{x";
	return temp;
}

std::string format( const unsigned& length, const int& number, char color ) {
	std::string message;
	message << number;
	return format( length, message, color );
}

std::string& format( const unsigned& length, const std::string& message, std::string& temp, char color ) {
	temp.clear();
	temp << '{' << color << message;
	for ( unsigned u = message.length(); u < length; ++u )
		temp << ' ';
	temp << "{x";
	return temp;
}

std::string& format( const unsigned& length, const int& number, std::string& temp, char color ) {
	std::string message;
	message << number;
	return format( length, message, temp, color );
}

bool strstr( const std::string& str1, const std::string& str2 ) {
	if ( strstr( lowerString( str1 ).c_str(), lowerString( str2 ).c_str() ) == 0 ) {
		return false;
	}
	return true;
}

bool str_prefix( const std::string& str1, const std::string& str2 ) {
	std::string temp = lowerString( str2 ).substr( 0, str1.length() );
	return ( lowerString( str1 ) == temp );
}

////////////////////////////////////////////////  Split ///////////////////////////////////////////////////
//////////////
// Get Word //
//////////////
std::string::const_iterator getword ( const std::string& src, std::string& dest, const char delim ) {
	return getword( src.begin(), src.end(), dest, delim );
}

std::string::const_iterator getword ( std::string::const_iterator it, std::string::const_iterator end, std::string& dest, const char delim ) {
	for ( ; it != end; ++it ) {
		if ( *it == delim ) {
			++it;
			break;
		}
		dest += *it;
	}
	return it;
}

/////////////////
// Split Delim //
/////////////////
std::vector< std::string > split( const std::string& src, char delim ) {
	std::vector< std::string > dest;
    std::string current;
 
	for ( std::string::const_iterator c = src.begin(); c != src.end(); ++c ) {
		if ( (*c) == delim ) {
			dest.push_back( current );
 		   current = "";
			continue;
 	   } else {
 	   	current.push_back( (*c) );
 	   }
	}
 
    if ( !current.empty() )
    	dest.push_back( current );
 
    return dest;
}

std::string::const_iterator split( const std::string& src, std::string& word1, char delim ) {
	return getword( src, word1, delim );
}
std::string::const_iterator split( const std::string& src, std::string& word1, std::string& word2, char delim ) {
	return getword( getword( src, word1, delim ), src.end(), word2, delim );
}
std::string::const_iterator split( const std::string& src, std::string& word1, std::string& word2, std::string& word3, char delim ) {
    return getword( getword( getword(src, word1, delim ), src.end(), word2, delim ), src.end(), word3, delim );
}
std::string::const_iterator split( const std::string& src, std::string& word1, std::string& word2, std::string& word3, std::string& word4, char delim ) {
    return getword( getword( getword( getword( src, word1, delim ), src.end(), word2, delim ), src.end(), word3, delim ), src.end(), word4, delim );
}

///////////
// Split //
///////////
std::string::const_iterator split( const std::string& src, std::string& word1 ) {
	return getword( src, word1, '\0' );
}
std::string::const_iterator split( const std::string& src, std::string& word1, std::string& word2 ) {
	return getword( getword( src, word1 ), src.end(), word2, '\0' );
}
std::string::const_iterator split( const std::string& src, std::string& word1, std::string& word2, std::string& word3 ) {
	return getword( getword( getword( src, word1 ), src.end(), word2 ), src.end(), word3, '\0' );
}
std::string::const_iterator split ( const std::string& src, std::string& word1, std::string& word2, std::string& word3, std::string& word4 ) {
	return getword( getword( getword( getword( src, word1 ), src.end(), word2 ), src.end(), word3 ), src.end(), word4, '\0' );
}


/*string quotesSplit( const std::string& src, std::string& dest ) {
	std::string::const_iterator it;
	
	for ( it = src.begin(); it != src.end(); ++it ) {
	}
}*/

